package packagerars;

import com.enterprisedt.net.ftp.FTPTransferType;
import com.enterprisedt.net.ftp.FileTransferClient;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Ronald
 */
public class Compresor {

    /**
     * logger : Objeto encargado de los log en la aplicacion.
     */
    private  final Log logger = LogFactory.getLog(Compresor.class);
    /**
     * Constante que define el buffer del archivo a comprimir.
     */
    private  final int bufferSize = 4096;
    /**
     * parametros del shell .
     */
    private  Map params = null;
    /**
     * filesZip .
     */
    private  List filesZip = new ArrayList();
    /**
     * filesZip .
     */
    /**
     * swZipGeneral .
     */
    private  boolean swZipGeneral = false;
    /**
     * swArchivosNoAgrupados.
     */
    private  boolean swArchivosNoAgrupados = false;
    /**
     * sufijo .
     */
    private  String sufijo = ";archivo.zip";
    /**
     * formateador de la fecha .
     */
    private SimpleDateFormat formateador =
            new SimpleDateFormat("dd-MM-yyyy-hh-mm");
    /**
     * Fecha de creacion del archivos .
     */
    private String fecha = formateador.format(new Date());
    /**
     * nombreArchivoZipGeneral .
     */
    private  String nombreArchivoZipGeneral =
            "personalizacion" + fecha + ".zip";
    /**
     * PLANTILLA_HTML .
     */
    private static final String PLANTILLA_HTML = "<HTML>"
                    + "<HEAD>"
                    + "    <TITLE>Detalle de Facturas Enviadas</TITLE>"
                    + "   <style type='text/css'>"
                    + "       table,td,th {"
                    + "           border-collapse:collapse;"
                    + "           margin:0;"
                    + "         padding:0;"
                    + "    }"
                    + " table {"
                    + "  border: none;"
                    + " font-family: Garamond, Georgia,"
                    + " 'Times New Roman', Times, serif;"
                    + "}"
                    + "table caption {"
                    + "background-color: transparent;"
                    + "background-image: url(cap_bg.gif);"
                    + "background-repeat: repeat-x;"
                    + "background-position: bottom left;"
                    + "text-align:left;"
                    + "font-size:150%;"
                    + "text-transform:uppercase;"
                    + "line-height: 30px;"
                    + "letter-spacing:0px;"
                    + "}"
                    + "td, th{"
                    + "                vertical-align:top;"
                    + "                font-weight:normal;"
                    + "            }"
                    + "            thead {"
                    + "                border-left:1px solid #2293FF;"
                    + "            }"
                    + "            thead th {"
                    + "                background: #2293FF;"
                    + "                color: #FFFFFF;"
                    + "                font-size: 125%;"
                    + "                border-top:1px solid #2293FF;"
                    + "                border-right:1px solid #2293FF;"
                    + "                padding: 4px 0.4em 4px 0.4em;"
                    + "            }"
                    + "tfoot td, tfoot th {"
                    + "                border-top:1px solid #2293FF;"
                    + "                border-right: none;"
                    + "                font-weight: bolder;"
                    + "                font-size: 110%;"
                    + "                padding: 0.4em 0.5em 0.4em 0.5em;"
                    + "            }"
                    + "            tbody td, tbody th {"
                    + "                background-color: #D9ECFF;"
                    + "                border-right:1px solid #2293FF;"
                    + "                font-size: 110%;"
                    + "                padding: 0.4em 0.5em 0.4em 0.5em;"
                    + "            }"
                    + "            tbody tr.odd th, tbody tr.odd td{"
                    + "                background-color: #BDDFFF;"
                    + "            }"
                    + "            tbody th{"
                    + "                font-weight: bold;"
                    + "                border-left:1px solid #2293FF"
                    + "            }"
                    + "            table a:link, table a:visited,"
                    + " table a:active {"
                    + "                color:#444F66;"
                    + "                background-color: transparent;"
                    + "                text-decoration: underline;"
                    + "            }"
                    + "            table a:hover {"
                    + "                text-decoration:none;"
                    + "                background-color: #1E90FF;"
                    + "                color: #FFFFFF;"
                    + "            }"
                    + "        </style>"
                    + "    </HEAD>"
                    + "    <BODY>"
                    + "        <div align='center'>"
                    + "            <table  >"
                    + "                <tr>"
                    + "                    <td colspan='6' align='center'>"
                    + "                        <b>Detalle de Facturas"
                    + " Enviadas</b>"
                    + "                    </td>"
                    + "                </tr>"
                    + "                <tr>"
                    + "                    <td >"
                    + "                        #"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        Codigo"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        Nombre Cliente"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        fecha"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        Nombre Archivo"
                    + "                    </td>"
                    + "               </tr>";

    /**
     * compresor .
     * @param urlRaiz .
     * @param urlArchivo .
     * @param agrupar .
     * @param userPTF .
     * @param passFTP .
     * @param hostFTP .
     * @param portFTP .
     * @param enviarFTP .
     * @param nombreArchivos .
     */
    public void compresor(final String urlRaiz,
            final String urlArchivo,
            final String agrupar,
            final String userPTF,
            final String passFTP,
            final String hostFTP,
            final String portFTP,
            final boolean enviarFTP,
            final String nombreArchivos) {

        boolean exitoEnvio = false;
        params = new HashMap();
        params.put("urlRaiz", urlRaiz + File.separator);
        params.put("urlAchivo", urlArchivo);
        params.put("agrupar", agrupar);
        params.put("userFTP", userPTF);
        params.put("passFTP", passFTP);
        params.put("hostFTP", hostFTP);
        params.put("portFTP", portFTP);
        logger.info("Inicio compresion.");
        File f = new File(params.get("urlRaiz").toString());
        BufferedReader entrada = null;
        Map mapaCorreo = new HashMap();
        List listaArchivoNoAgrupados = new ArrayList();
        try {
            entrada = new BufferedReader(
                    new FileReader(params.get("urlAchivo").toString()));
            if (f.exists()) {
                int linea = 1;
                while (entrada.ready()) {
                    String texto = entrada.readLine();
                    String[] cadena = texto.split("\\|");
                    if (cadena.length != 9) {
                        logger.info("Problemas con  longitud de la linea:"
                                + linea);
                    }
                    try {
                        Integer.parseInt(cadena[0].substring(0, 2));
                        if (params.get("agrupar").toString().
                                equals("agrupar")) {
                            if (!mapaCorreo.containsKey(cadena[8])) {
                                List listaArchivosAgrupados = new ArrayList();
                                List listaCodigo = new ArrayList();
                                List listaCliente = new ArrayList();
                                List listaFecha = new ArrayList();

                                listaCodigo.add(cadena[0]);
                                listaCliente.add(cadena[1]);
                                listaFecha.add(cadena[5]);
                                listaArchivosAgrupados.add(cadena[7]);
                                Map mapCampos = new HashMap();
                                mapCampos.put("codigos", listaCodigo);
                                mapCampos.put("clientes", listaCliente);
                                mapCampos.put("fechas", listaFecha);
                                mapCampos.put("pdfs", listaArchivosAgrupados);
                                mapaCorreo.put(cadena[8], mapCampos);
                            } else {
                                Map mapTemp = (Map) mapaCorreo.get(cadena[8]);
                                List listaPdfTemp =
                                        (List) mapTemp.get("pdfs");
                                List listaCodigoTemp =
                                        (List) mapTemp.get("codigos");
                                List listaClienteTemp =
                                        (List) mapTemp.get("clientes");
                                List listaFechaTemp =
                                        (List) mapTemp.get("fechas");
                                listaCodigoTemp.add(cadena[0]);
                                listaClienteTemp.add(cadena[1]);
                                listaFechaTemp.add(cadena[5]);
                                listaPdfTemp.add(cadena[7]);
                                mapTemp.put("codigos", listaCodigoTemp);
                                mapTemp.put("clientes", listaClienteTemp);
                                mapTemp.put("fechas", listaFechaTemp);
                                mapTemp.put("pdfs", listaPdfTemp);
                                mapaCorreo.put(cadena[8], mapTemp);
                            }
                        } else {
                            listaArchivoNoAgrupados.add(
                                    cadena[7] + ";" + cadena[8]);
                        }
                    } catch (Exception ex) {
                        logger.info("Problema con la lectura de la linea "
                                + linea);

                    }
                    linea++;
                }
                if (mapaCorreo.size() > 0) {
                    Iterator it = mapaCorreo.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry e = (Map.Entry) it.next();
                        crearIndex((Map) e.getValue(), params.get("urlRaiz").
                                toString() + "index.html");
                        List listaArchivos = new ArrayList();
                        listaArchivos =
                                (List) ((Map) e.getValue()).get("pdfs");
                        listaArchivos.add("index.html");
                        String nomArchivo = e.getKey().toString() + sufijo;
                        comprimir(listaArchivos, params.get("urlRaiz").
                                toString(), nomArchivo);
                        File archivoElminado = new File(params.get("urlRaiz").
                                toString() + "index.html");
                        archivoElminado.delete();
                    }
                } else {
                    if (listaArchivoNoAgrupados.size() > 0) {
                        boolean exitoCompresion = false;
                        if (nombreArchivos == null || nombreArchivos.equals("")
                                || nombreArchivos.equals(" ")) {
                        exitoCompresion = comprimir(listaArchivoNoAgrupados,
                                params.get("urlRaiz").toString(),
                                nombreArchivoZipGeneral);
                        } else {
                            exitoCompresion = comprimir(listaArchivoNoAgrupados,
                                params.get("urlRaiz").toString(),
                                nombreArchivos + ".zip");
                        }
                        if (exitoCompresion) {
                            if (nombreArchivos == null || nombreArchivos.equals("")
                                    || nombreArchivos.equals(" ")) {
                                logger.info("Fin de compresión del archivo. "
                                        + "\nNombre del "
                                        + "archivo:" + nombreArchivoZipGeneral);

                            } else {
                             logger.info("Fin de compresión del archivo. "
                                        + "\nNombre del "
                                        + "archivo:" + nombreArchivos + ".zip");
                            }
                        } else {
                            logger.info("Problemas en el proceso de"
                                    + " compresión,\n"
                                    + "vea el log para mas información  ");
                        }
                        swArchivosNoAgrupados = true;
                        if (enviarFTP && exitoCompresion) {
                            Map param = new HashMap();
                            param.put("host", params.get("hostFTP"));
                            param.put("user", params.get("userFTP"));
                            param.put("pass", params.get("passFTP"));
                            param.put("port", params.get("portFTP"));
                            if (nombreArchivos == null || nombreArchivos.equals("")
                                    || nombreArchivos.equals(" ")) {
                                param.put("urlArchivo", params.get("urlRaiz").
                                        toString() + nombreArchivoZipGeneral);
                                param.put("nomArchivo", nombreArchivoZipGeneral);

                            } else {
                                param.put("urlArchivo", params.get("urlRaiz").
                                        toString() + nombreArchivos + ".zip");
                                param.put("nomArchivo", nombreArchivos + ".zip");
                            }


                            exitoEnvio = enviarArchivo(param);
                            if (exitoEnvio) {
                                if (nombreArchivos == null || nombreArchivos.equals("")
                                        || nombreArchivos.equals(" ")) {
                                    logger.info("Fin de envio via FTP. \n"
                                            + "Nombre del "
                                            + "archivo:" + nombreArchivoZipGeneral);
                                } else {
                                    logger.info("Fin de envio via FTP. \n"
                                            + "Nombre del "
                                            + "archivo:" + nombreArchivos + ".zip");
                                }

                            } else {
                                logger.info("Problemas en el envio "
                                        + "via FTP,\n"
                                        + "vea el log para mas información ");
                            }
                        }
                    }
                }
            }
        } catch (IOException ex) {
            logger.error("Problemas con la lectura del archivo: " + ex);
        }
        if (!swArchivosNoAgrupados) {
            swZipGeneral = true;
            logger.info("Inicio de compresión del archivo.");
            boolean exitoCompresion = false;
            if (nombreArchivos == null || nombreArchivos.equals("")
                                        || nombreArchivos.equals(" ")) {
                exitoCompresion = comprimir(filesZip,
                    params.get("urlRaiz").toString(),
                    nombreArchivoZipGeneral);
            } else {
                exitoCompresion = comprimir(filesZip,
                    params.get("urlRaiz").toString(),
                    nombreArchivos + ".zip");
            }

            if (exitoCompresion) {
                if (nombreArchivos == null || nombreArchivos.equals("")
                        || nombreArchivos.equals(" ")) {
                    logger.info("Fin de compresión del archivo. \n Nombre del "
                            + "archivo:" + nombreArchivoZipGeneral);
                } else {
                    logger.info("Fin de compresión del archivo. \n Nombre del "
                            + "archivo:" + nombreArchivos + ".zip");
                }

            } else {
                logger.info("Problemas en el proceso de compresión,\n"
                        + "vea el log para mas información  ");
            }
            if (enviarFTP && exitoCompresion) {
                Map param = new HashMap();
                param.put("host", params.get("hostFTP"));
                param.put("user", params.get("userFTP"));
                param.put("pass", params.get("passFTP"));
                param.put("port", params.get("portFTP"));
                if (nombreArchivos == null || nombreArchivos.equals("")
                        || nombreArchivos.equals(" ")) {
                    param.put("urlArchivo", params.get("urlRaiz").toString()
                            + nombreArchivoZipGeneral);
                    param.put("nomArchivo", nombreArchivoZipGeneral);
                } else {
                    param.put("urlArchivo", params.get("urlRaiz").toString()
                            + nombreArchivos + ".zip");
                    param.put("nomArchivo", nombreArchivos + ".zip");
                }
                exitoEnvio = enviarArchivo(param);
                if (exitoEnvio) {
                    if (nombreArchivos == null || nombreArchivos.equals("")
                            || nombreArchivos.equals(" ")) {
                        logger.info("Fin de envio via FTP. \n Nombre del "
                                + "archivo:" + nombreArchivoZipGeneral);
                    } else {
                        logger.info("Fin de envio via FTP. \n Nombre del "
                                + "archivo:" + nombreArchivos + ".zip");
                    }
                } else {
                    logger.info("Problemas en el envio via FTP,\n"
                            + "vea el log para mas información  ");
                }
            }
        }

    }

    /**
     * Metodo que comprime los archivos .
     * @param files .
     * @param urlRaz .
     * @param nombreArchivoSalida .
     * @return boolean .
     */
    public  boolean  comprimir(final List files, final String urlRaz,
            final String nombreArchivoSalida) {
        boolean exitoComprimir =  true;
        if (!swZipGeneral) {
            filesZip.add(nombreArchivoSalida);
        }
        try {
            BufferedInputStream origin = null;

            FileOutputStream dest = new FileOutputStream(
                    new File(urlRaz + nombreArchivoSalida));

            ZipOutputStream out = new ZipOutputStream(
                    new BufferedOutputStream(dest));
            byte[] data = new byte[bufferSize];
            for (Iterator i = files.iterator(); i.hasNext();) {
                String[] arrayNombre = ((String) i.next()).split(";");
                String nombreArchivoEntrada = "";
                if (!swZipGeneral) {
                    if (!params.get("agrupar").toString().equals("agrupar")) {
                        nombreArchivoEntrada = arrayNombre[0];
                    } else {
                        nombreArchivoEntrada = arrayNombre[0];
                    }
                } else {
                    nombreArchivoEntrada = arrayNombre[0] + sufijo;
                }
                String filename = urlRaz + nombreArchivoEntrada;
                File file = new File(filename);
                FileInputStream fi = new FileInputStream(file);
                origin = new BufferedInputStream(fi, bufferSize);
                String nombreArchivoComprimido = "";
                if (swArchivosNoAgrupados) {
                    nombreArchivoComprimido = arrayNombre[0];
                } else {
                    if (arrayNombre.length > 1) {
                        if (params.get("agrupar").toString().
                                equals("agrupar")) {
                            nombreArchivoComprimido = arrayNombre[0] + ";"
                                    + arrayNombre[1];
                        } else {
                            nombreArchivoComprimido = arrayNombre[1]
                                    + ";" + arrayNombre[0];
                        }

                    } else {
                        nombreArchivoComprimido = file.getName();
                    }
                }
                ZipEntry entry = new ZipEntry(nombreArchivoComprimido);
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, bufferSize)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
                if (swZipGeneral) {
                    if (!file.delete()) {
                        logger.info("Problemas para elminar el archivo"
                                + file.getName());
                    }
                }
            }
            out.close();
        } catch (Exception ex) {
            logger.error("Problemas para comprimir el archivo " + ex);
            exitoComprimir = false;
        }
        return exitoComprimir;
    }

    /**
     * Metodo que crea el arhivo index.html .
     * @param mapCampos .
     * @param urlArchivo .
     */
    public  void crearIndex(final Map mapCampos, final String urlArchivo) {
        FileWriter fichero = null;
        PrintWriter pw = null;
        try {
            File archivo = new File(urlArchivo);
            fichero = new FileWriter(archivo, true);
            pw = new PrintWriter(fichero);
            pw.write(PLANTILLA_HTML);
            Iterator it = mapCampos.entrySet().iterator();
            List listaPdf = new ArrayList();
            List listaCodigo = new ArrayList();
            List listaCliente = new ArrayList();
            List listaFecha = new ArrayList();
            while (it.hasNext()) {
                Map.Entry e = (Map.Entry) it.next();
                if (e.getKey().equals("codigos")) {
                    listaCodigo = (List) e.getValue();
                }
                if (e.getKey().equals("pdfs")) {
                    listaPdf = (List) e.getValue();
                }
                if (e.getKey().equals("clientes")) {
                    listaCliente = (List) e.getValue();
                }
                if (e.getKey().equals("fechas")) {
                    listaFecha = (List) e.getValue();
                }
            }
            for (int i = 0; i < listaCliente.size(); i++) {
                String cliente = (String) listaCliente.get(i);
                String pdf = (String) listaPdf.get(i);
                String codigo = (String) listaCodigo.get(i);
                String fechaIndex = (String) listaFecha.get(i);
                pw.write("        <tr>"
                        + "            <td >"
                        + new Integer(i + 1)
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + codigo
                        + "                 </a>"
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + cliente
                        + "                </a>"
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + fechaIndex
                        + "                </a>"
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + pdf
                        + "                    </a>"
                        + "            </td>"
                        + "         </tr>");
            }

            pw.write("</table> "
                    + " </div> "
                    + "</BODY> "
                    + "</HTML> ");
            fichero.close();
        } catch (Exception e) {
            logger.error("Problemar creando el archivo index.html:" + e);
        }
    }

    /**
     *
     *Metodo encargado de enviar archivo via ftp.
     * @param newParams .
     * @return  boolean .
     */
    public  boolean enviarArchivo(final Map newParams) {
        boolean exitoEnvio = true;
        FileTransferClient ftpTransferClient = new FileTransferClient();
        try {
            ftpTransferClient.setRemoteHost((String) newParams.get("host"));
            ftpTransferClient.setUserName((String) newParams.get("user"));
            ftpTransferClient.setPassword((String) newParams.get("pass"));
            ftpTransferClient.setRemotePort((
                    new Integer((String) newParams.get("port"))));
            ftpTransferClient.connect();
            ftpTransferClient.setContentType(FTPTransferType.BINARY);
            ftpTransferClient.changeDirectory("/");
            ftpTransferClient.setDetectContentType(true);
            File source = new File((String) newParams.get("urlArchivo"));
            OutputStream os = ftpTransferClient.uploadStream(
                    (String) newParams.get("nomArchivo"));
            FileInputStream fis = new FileInputStream(source);
            long fin = source.length();
            long ini = 0;
            int x = 0;
            byte[] b = new byte[2048];
            while ((x = fis.read(b)) > 0) {
                ini += x;
                os.write(b, 0, x);
            }
            os.close();
            fis.close();
        } catch (Exception ex) {
            exitoEnvio = false;
        }
        return exitoEnvio;
    }

}
